using System;
using System.Collections.Generic;
using System.Text;

namespace OracleInternal.I18N
{
	internal class UTF16ConvAL32UTF8 : Conv
	{
		private static UTF16ConvUtility.ConvertToCharsDelegate<char> ConvertBytesToCharsInstance = ConvertBytesToCharsImpl;

		private static UTF16ConvUtility.ConvertToCharsDelegate<byte> ConvertBytesToUTF16Instance = ConvertBytesToUTF16Impl;

		private static UTF16ConvUtility.GetCharsLengthDelegate GetCharsLengthInstance = GetCharsLengthImpl;

		private static UTF16ConvUtility.GetBytesOffsetDelegate GetBytesOffsetInstance = GetBytesOffsetImpl;

		public override int MinBytesPerChar => 1;

		public override int MaxBytesPerChar => 4;

		internal UTF16ConvAL32UTF8(int oracleId)
			: base(oracleId)
		{
		}

		private static int GetCharsLengthImpl(byte[] bytes, int byteOffset, int byteCount, ref int bytesCounted)
		{
			int num = 0;
			int num2 = byteOffset;
			int num3 = byteOffset + byteCount;
			if (num3 > bytes.Length)
			{
				num3 = bytes.Length;
			}
			bool flag = true;
			while (num2 < num3 && flag)
			{
				switch ((bytes[num2] & 0xF0) >> 4)
				{
				case 0:
				case 1:
				case 2:
				case 3:
				case 4:
				case 5:
				case 6:
				case 7:
					num2++;
					num++;
					break;
				case 12:
				case 13:
					if (num2 + 1 >= num3)
					{
						flag = false;
						bytesCounted = num2 - byteOffset;
					}
					else
					{
						num++;
						num2 += 2;
					}
					break;
				case 14:
					if (num2 + 2 >= num3)
					{
						flag = false;
						bytesCounted = num2 - byteOffset;
					}
					else
					{
						num++;
						num2 += 3;
					}
					break;
				case 15:
					if (num2 + 3 >= num3)
					{
						flag = false;
						bytesCounted = num2 - byteOffset;
					}
					else
					{
						num += 2;
						num2 += 4;
					}
					break;
				default:
					num2++;
					num++;
					break;
				}
			}
			bytesCounted = num2 - byteOffset;
			return num;
		}

		private static int GetBytesOffsetImpl(byte[] bytes, int byteOffset, int byteCount, ref int charCount)
		{
			int num = 0;
			int num2 = byteOffset;
			int num3 = byteOffset + byteCount;
			if (num3 > bytes.Length)
			{
				num3 = bytes.Length;
			}
			bool flag = true;
			while (num2 < num3 && flag && num < charCount)
			{
				switch ((bytes[num2] & 0xF0) >> 4)
				{
				case 0:
				case 1:
				case 2:
				case 3:
				case 4:
				case 5:
				case 6:
				case 7:
					num2++;
					num++;
					break;
				case 12:
				case 13:
					if (num2 + 1 >= num3)
					{
						flag = false;
						break;
					}
					num++;
					num2 += 2;
					break;
				case 14:
					if (num2 + 2 >= num3)
					{
						flag = false;
						break;
					}
					num++;
					num2 += 3;
					break;
				case 15:
					if (num2 + 3 >= num3)
					{
						flag = false;
						break;
					}
					num += 2;
					num2 += 4;
					break;
				default:
					num2++;
					num++;
					break;
				}
			}
			charCount = num;
			return num2 - byteOffset;
		}

		public override int GetBytesOffset(byte[] bytes, int byteOffset, int byteCount, int charCount)
		{
			int charCount2 = charCount;
			return GetBytesOffsetImpl(bytes, byteOffset, byteCount, ref charCount2);
		}

		public override int GetBytesLength(char[] chars, int charOffset, int charCount)
		{
			int num = charOffset;
			int num2 = charOffset + charCount;
			int num3 = 0;
			if (num < 0)
			{
				num = 0;
			}
			if (num2 > chars.Length)
			{
				num2 = chars.Length;
			}
			for (int i = num; i < num2; i++)
			{
				int num4 = chars[i];
				if (num4 >= 0 && num4 <= 127)
				{
					num3++;
				}
				else if (UTF16ConvUtility.IsHiSurrogate((char)num4))
				{
					if (i + 1 < num2 && UTF16ConvUtility.IsLoSurrogate(chars[i + 1]))
					{
						num3 += 4;
						i++;
					}
					else
					{
						num3 += 3;
					}
				}
				else
				{
					num3 = ((num4 <= 2047) ? (num3 + 2) : (num3 + 3));
				}
			}
			return num3;
		}

		public override int GetBytesLength(string chars, int charOffset, int charCount)
		{
			int num = charOffset;
			int num2 = charOffset + charCount;
			int num3 = 0;
			if (num < 0)
			{
				num = 0;
			}
			if (num2 > chars.Length)
			{
				num2 = chars.Length;
			}
			for (int i = num; i < num2; i++)
			{
				int num4 = chars[i];
				if (num4 >= 0 && num4 <= 127)
				{
					num3++;
				}
				else if (UTF16ConvUtility.IsHiSurrogate((char)num4))
				{
					if (i + 1 < num2 && UTF16ConvUtility.IsLoSurrogate(chars[i + 1]))
					{
						num3 += 4;
						i++;
					}
					else
					{
						num3 += 3;
					}
				}
				else
				{
					num3 = ((num4 <= 2047) ? (num3 + 2) : (num3 + 3));
				}
			}
			return num3;
		}

		public override int GetBytesLength(byte[] utf16Bytes, int utf16BytesOffset, int utf16BytesCount)
		{
			int num = utf16BytesOffset;
			int num2 = utf16BytesOffset + utf16BytesCount;
			int num3 = 0;
			if (num < 0)
			{
				num = 0;
			}
			if (num2 > utf16Bytes.Length)
			{
				num2 = utf16Bytes.Length;
			}
			for (int i = num; i < num2 - 1; i += 2)
			{
				int num4 = (utf16Bytes[i + 1] << 8) | utf16Bytes[i];
				if (num4 >= 0 && num4 <= 127)
				{
					num3++;
				}
				else if (UTF16ConvUtility.IsHiSurrogate((char)num4))
				{
					if (i + 3 < num2 && UTF16ConvUtility.IsLoSurrogate((char)((utf16Bytes[i + 3] << 8) | utf16Bytes[i + 2])))
					{
						num3 += 4;
						i += 2;
					}
					else
					{
						num3 += 3;
					}
				}
				else
				{
					num3 = ((num4 <= 2047) ? (num3 + 2) : (num3 + 3));
				}
			}
			return num3;
		}

		public override int ConvertCharsToBytes(char[] chars, int chars_offset, int chars_count, byte[] bytes, int bytes_begin, ref int bytes_count, bool bUseReplacementChar)
		{
			int num = chars_offset;
			int num2 = chars_offset + chars_count;
			if (num < 0)
			{
				num = 0;
			}
			if (num2 > chars.Length)
			{
				num2 = chars.Length;
			}
			if (bytes_begin < 0)
			{
				bytes_begin = 0;
			}
			int num3 = bytes_begin + bytes_count;
			if (num3 > bytes.Length)
			{
				num3 = bytes.Length;
			}
			int num4 = bytes_begin;
			int i;
			for (i = num; i < num2; i++)
			{
				if (num4 >= num3)
				{
					break;
				}
				int num5 = chars[i];
				int num6 = 0;
				if (num5 >= 0 && num5 <= 127)
				{
					bytes[num4++] = (byte)num5;
				}
				else if (UTF16ConvUtility.IsHiSurrogate((char)num5))
				{
					if (i + 1 < num2 && UTF16ConvUtility.IsLoSurrogate((char)(num6 = chars[i + 1])))
					{
						if (num4 + 3 >= num3)
						{
							break;
						}
						int num7 = ((num5 >> 6) & 0xF) + 1;
						bytes[num4++] = (byte)((uint)(num7 >> 2) | 0xF0u);
						bytes[num4++] = (byte)((uint)((num7 & 3) << 4) | ((uint)(num5 >> 2) & 0xFu) | 0x80u);
						bytes[num4++] = (byte)((uint)((num5 & 3) << 4) | ((uint)(num6 >> 6) & 0xFu) | 0x80u);
						bytes[num4++] = (byte)(((uint)num6 & 0x3Fu) | 0x80u);
						i++;
					}
					else
					{
						if (num4 + 2 >= num3)
						{
							break;
						}
						bytes[num4++] = Conv.REP_CHAR_UTF8[0];
						bytes[num4++] = Conv.REP_CHAR_UTF8[1];
						bytes[num4++] = Conv.REP_CHAR_UTF8[2];
					}
				}
				else if (num5 > 2047)
				{
					if (num4 + 2 >= num3)
					{
						break;
					}
					bytes[num4++] = (byte)(0xE0u | ((uint)(num5 >> 12) & 0xFu));
					bytes[num4++] = (byte)(0x80u | ((uint)(num5 >> 6) & 0x3Fu));
					bytes[num4++] = (byte)(0x80u | ((uint)num5 & 0x3Fu));
				}
				else
				{
					if (num4 + 1 >= num3)
					{
						break;
					}
					bytes[num4++] = (byte)(0xC0u | ((uint)(num5 >> 6) & 0x1Fu));
					bytes[num4++] = (byte)(0x80u | ((uint)num5 & 0x3Fu));
				}
			}
			bytes_count = num4 - bytes_begin;
			return i - num;
		}

		public override int ConvertStringToBytes(string chars, int chars_offset, int chars_count, byte[] bytes, int bytes_begin, ref int bytes_count, bool bUseReplacementChar)
		{
			int num = chars_offset;
			int num2 = chars_offset + chars_count;
			if (num < 0)
			{
				num = 0;
			}
			if (num2 > chars.Length)
			{
				num2 = chars.Length;
			}
			if (bytes_begin < 0)
			{
				bytes_begin = 0;
			}
			int num3 = bytes_begin + bytes_count;
			if (num3 > bytes.Length)
			{
				num3 = bytes.Length;
			}
			int num4 = bytes_begin;
			int i;
			for (i = num; i < num2; i++)
			{
				if (num4 >= num3)
				{
					break;
				}
				int num5 = chars[i];
				int num6 = 0;
				if (num5 >= 0 && num5 <= 127)
				{
					bytes[num4++] = (byte)num5;
				}
				else if (UTF16ConvUtility.IsHiSurrogate((char)num5))
				{
					if (i + 1 < num2 && UTF16ConvUtility.IsLoSurrogate((char)(num6 = chars[i + 1])))
					{
						if (num4 + 3 >= num3)
						{
							break;
						}
						int num7 = ((num5 >> 6) & 0xF) + 1;
						bytes[num4++] = (byte)((uint)(num7 >> 2) | 0xF0u);
						bytes[num4++] = (byte)((uint)((num7 & 3) << 4) | ((uint)(num5 >> 2) & 0xFu) | 0x80u);
						bytes[num4++] = (byte)((uint)((num5 & 3) << 4) | ((uint)(num6 >> 6) & 0xFu) | 0x80u);
						bytes[num4++] = (byte)(((uint)num6 & 0x3Fu) | 0x80u);
						i++;
					}
					else
					{
						if (num4 + 2 >= num3)
						{
							break;
						}
						bytes[num4++] = Conv.REP_CHAR_UTF8[0];
						bytes[num4++] = Conv.REP_CHAR_UTF8[1];
						bytes[num4++] = Conv.REP_CHAR_UTF8[2];
					}
				}
				else if (num5 > 2047)
				{
					if (num4 + 2 >= num3)
					{
						break;
					}
					bytes[num4++] = (byte)(0xE0u | ((uint)(num5 >> 12) & 0xFu));
					bytes[num4++] = (byte)(0x80u | ((uint)(num5 >> 6) & 0x3Fu));
					bytes[num4++] = (byte)(0x80u | ((uint)num5 & 0x3Fu));
				}
				else
				{
					if (num4 + 1 >= num3)
					{
						break;
					}
					bytes[num4++] = (byte)(0xC0u | ((uint)(num5 >> 6) & 0x1Fu));
					bytes[num4++] = (byte)(0x80u | ((uint)num5 & 0x3Fu));
				}
			}
			bytes_count = num4 - bytes_begin;
			return i - num;
		}

		public override int ConvertUTF16ToBytes(byte[] utf16Bytes, int utf16BytesOffset, int utf16BytesCount, byte[] bytes, int byteOffset, ref int byteCount, bool bUseReplacementChar = true)
		{
			int num = utf16BytesOffset;
			int num2 = utf16BytesOffset + utf16BytesCount;
			if (num < 0)
			{
				num = 0;
			}
			if (num2 > utf16Bytes.Length)
			{
				num2 = utf16Bytes.Length;
			}
			if (byteOffset < 0)
			{
				byteOffset = 0;
			}
			int num3 = byteOffset + byteCount;
			if (num3 > bytes.Length)
			{
				num3 = bytes.Length;
			}
			int num4 = byteOffset;
			int i;
			for (i = num; i < num2 - 1; i += 2)
			{
				if (num4 >= num3)
				{
					break;
				}
				int num5 = (utf16Bytes[i + 1] << 8) | utf16Bytes[i];
				int num6 = 0;
				if (num5 >= 0 && num5 <= 127)
				{
					bytes[num4++] = (byte)num5;
				}
				else if (UTF16ConvUtility.IsHiSurrogate((char)num5))
				{
					if (i + 3 < num2 && UTF16ConvUtility.IsLoSurrogate((char)(num6 = (utf16Bytes[i + 3] << 8) | utf16Bytes[i + 2])))
					{
						if (num4 + 3 >= num3)
						{
							break;
						}
						int num7 = ((num5 >> 6) & 0xF) + 1;
						bytes[num4++] = (byte)((uint)(num7 >> 2) | 0xF0u);
						bytes[num4++] = (byte)((uint)((num7 & 3) << 4) | ((uint)(num5 >> 2) & 0xFu) | 0x80u);
						bytes[num4++] = (byte)((uint)((num5 & 3) << 4) | ((uint)(num6 >> 6) & 0xFu) | 0x80u);
						bytes[num4++] = (byte)(((uint)num6 & 0x3Fu) | 0x80u);
						i += 2;
					}
					else
					{
						if (num4 + 2 >= num3)
						{
							break;
						}
						bytes[num4++] = Conv.REP_CHAR_UTF8[0];
						bytes[num4++] = Conv.REP_CHAR_UTF8[1];
						bytes[num4++] = Conv.REP_CHAR_UTF8[2];
					}
				}
				else if (num5 > 2047)
				{
					if (num4 + 2 >= num3)
					{
						break;
					}
					bytes[num4++] = (byte)(0xE0u | ((uint)(num5 >> 12) & 0xFu));
					bytes[num4++] = (byte)(0x80u | ((uint)(num5 >> 6) & 0x3Fu));
					bytes[num4++] = (byte)(0x80u | ((uint)num5 & 0x3Fu));
				}
				else
				{
					if (num4 + 1 >= num3)
					{
						break;
					}
					bytes[num4++] = (byte)(0xC0u | ((uint)(num5 >> 6) & 0x1Fu));
					bytes[num4++] = (byte)(0x80u | ((uint)num5 & 0x3Fu));
				}
			}
			byteCount = num4 - byteOffset;
			return i - num;
		}

		private static int ConvertBytesToCharsImpl(byte[] bytes, int offset, int count, char[] chars, int charOffset, ref int charCount, bool ccb)
		{
			int num = offset;
			if (num < 0)
			{
				num = 0;
			}
			int num2 = num + count;
			if (num2 > bytes.Length)
			{
				num2 = bytes.Length;
			}
			int num3 = charOffset;
			if (num3 < 0)
			{
				num3 = 0;
			}
			int num4 = num3 + charCount;
			if (num4 > chars.Length)
			{
				num4 = chars.Length;
			}
			bool flag = true;
			while (num < num2 && num3 < num4 && flag)
			{
				byte b = bytes[num++];
				switch ((b & 0xF0) / 16)
				{
				case 0:
				case 1:
				case 2:
				case 3:
				case 4:
				case 5:
				case 6:
				case 7:
					chars[num3++] = (char)(b & 0xFFu);
					break;
				case 12:
				case 13:
				{
					if (num >= num2)
					{
						if (!ccb)
						{
							throw new DecoderFallbackException(I18nStringResourceManager.GetErrorMesg("FAIL_CONV_TO_UNICODE"));
						}
						flag = false;
						num--;
						break;
					}
					char c = ((b >= 194 && b <= 223 && (bytes[num] & 0xC0) == 128) ? ((char)((uint)((b & 0x1F) << 6) | (bytes[num] & 0x3Fu))) : '\ufffd');
					num++;
					chars[num3++] = c;
					if (ccb || c != '\ufffd')
					{
						break;
					}
					throw new DecoderFallbackException(I18nStringResourceManager.GetErrorMesg("FAIL_CONV_TO_UNICODE"));
				}
				case 14:
				{
					if (num + 1 >= num2)
					{
						if (!ccb)
						{
							throw new DecoderFallbackException(I18nStringResourceManager.GetErrorMesg("FAIL_CONV_TO_UNICODE"));
						}
						flag = false;
						num--;
						break;
					}
					char c = (((b == 224 && (bytes[num] & 0xE0) == 160 && (bytes[num + 1] & 0xC0) == 128) || (b >= 225 && b <= 236 && (bytes[num] & 0xC0) == 128 && (bytes[num + 1] & 0xC0) == 128) || (b == 237 && (bytes[num] & 0xE0) == 128 && (bytes[num + 1] & 0xC0) == 128) || (b >= 238 && b <= 239 && (bytes[num] & 0xC0) == 128 && (bytes[num + 1] & 0xC0) == 128)) ? ((char)((uint)(((b & 0xF) << 12) | ((bytes[num] & 0x3F) << 6)) | (bytes[num + 1] & 0x3Fu))) : '\ufffd');
					num += 2;
					chars[num3++] = c;
					if ((b == Conv.REP_CHAR_UTF8[0] && bytes[num - 2] == Conv.REP_CHAR_UTF8[1] && bytes[num - 1] == Conv.REP_CHAR_UTF8[2]) || ccb || c != '\ufffd')
					{
						break;
					}
					throw new DecoderFallbackException(I18nStringResourceManager.GetErrorMesg("FAIL_CONV_TO_UNICODE"));
				}
				case 15:
				{
					if (num + 2 >= num2)
					{
						if (!ccb)
						{
							throw new DecoderFallbackException(I18nStringResourceManager.GetErrorMesg("FAIL_CONV_TO_UNICODE"));
						}
						flag = false;
						num--;
						break;
					}
					int num5 = 0;
					if ((b != 240 || (bytes[num] & 0xC0) != 128 || (bytes[num] & 0x30) == 0 || (bytes[num + 1] & 0xC0) != 128 || (bytes[num + 2] & 0xC0) != 128) && (b < 241 || b > 243 || (bytes[num] & 0xC0) != 128 || (bytes[num + 1] & 0xC0) != 128 || (bytes[num + 2] & 0xC0) != 128) && (b != 244 || (bytes[num] & 0xF0) != 128 || (bytes[num + 1] & 0xC0) != 128 || (bytes[num + 2] & 0xC0) != 128))
					{
						chars[num3] = '\ufffd';
						num5 = 1;
					}
					else if (num3 + 1 >= chars.Length)
					{
						num5 = 0;
					}
					else
					{
						chars[num3] = (char)((uint)(((((((b & 7) << 2) | ((bytes[num] >> 4) & 3)) - 1) & 0xF) << 6) | ((bytes[num] & 0xF) << 2)) | ((uint)(bytes[num + 1] >> 4) & 3u) | 0xD800u);
						chars[num3 + 1] = (char)((uint)((bytes[num + 1] & 0xF) << 6) | (bytes[num + 2] & 0x3Fu) | 0xDC00u);
						num5 = 2;
					}
					num += 3;
					switch (num5)
					{
					case 0:
						flag = false;
						num -= 4;
						break;
					case 1:
						if (!ccb)
						{
							throw new DecoderFallbackException(I18nStringResourceManager.GetErrorMesg("FAIL_CONV_TO_UNICODE"));
						}
						num3++;
						break;
					default:
						num3 += 2;
						break;
					}
					break;
				}
				default:
					chars[num3++] = '\ufffd';
					if (!ccb)
					{
						throw new DecoderFallbackException(I18nStringResourceManager.GetErrorMesg("FAIL_CONV_TO_UNICODE"));
					}
					break;
				}
			}
			charCount = num3 - charOffset;
			return num - offset;
		}

		public override int ConvertBytesToChars(byte[] bytes, int offset, int count, char[] chars, int charOffset, ref int charCount, bool ccb)
		{
			return ConvertBytesToCharsImpl(bytes, offset, count, chars, charOffset, ref charCount, ccb);
		}

		private static int ConvertBytesToUTF16Impl(byte[] bytes, int offset, int count, byte[] utfbytes, int utfOffset, ref int utfCount, bool ccb)
		{
			int num = offset;
			if (num < 0)
			{
				num = 0;
			}
			int num2 = num + count;
			if (num2 > bytes.Length)
			{
				num2 = bytes.Length;
			}
			int num3 = utfOffset;
			if (num3 < 0)
			{
				num3 = 0;
			}
			int num4 = num3 + utfCount;
			if (num4 > utfbytes.Length)
			{
				num4 = utfbytes.Length;
			}
			bool flag = true;
			while (num < num2 && num3 + 1 < num4 && flag)
			{
				byte b = bytes[num++];
				switch ((b & 0xF0) / 16)
				{
				case 0:
				case 1:
				case 2:
				case 3:
				case 4:
				case 5:
				case 6:
				case 7:
					utfbytes[num3++] = b;
					utfbytes[num3++] = 0;
					break;
				case 12:
				case 13:
				{
					if (num >= num2)
					{
						if (!ccb)
						{
							throw new DecoderFallbackException(I18nStringResourceManager.GetErrorMesg("FAIL_CONV_TO_UNICODE"));
						}
						flag = false;
						num--;
						break;
					}
					char c = ((b >= 194 && b <= 223 && (bytes[num] & 0xC0) == 128) ? ((char)((uint)((b & 0x1F) << 6) | (bytes[num] & 0x3Fu))) : '\ufffd');
					num++;
					if (!ccb && c == '\ufffd')
					{
						throw new DecoderFallbackException(I18nStringResourceManager.GetErrorMesg("FAIL_CONV_TO_UNICODE"));
					}
					utfbytes[num3++] = (byte)(c & 0xFFu);
					utfbytes[num3++] = (byte)((int)c >> 8);
					break;
				}
				case 14:
				{
					if (num + 1 >= num2)
					{
						if (!ccb)
						{
							throw new DecoderFallbackException(I18nStringResourceManager.GetErrorMesg("FAIL_CONV_TO_UNICODE"));
						}
						flag = false;
						num--;
						break;
					}
					char c = (((b == 224 && (bytes[num] & 0xE0) == 160 && (bytes[num + 1] & 0xC0) == 128) || (b >= 225 && b <= 236 && (bytes[num] & 0xC0) == 128 && (bytes[num + 1] & 0xC0) == 128) || (b == 237 && (bytes[num] & 0xE0) == 128 && (bytes[num + 1] & 0xC0) == 128) || (b >= 238 && b <= 239 && (bytes[num] & 0xC0) == 128 && (bytes[num + 1] & 0xC0) == 128)) ? ((char)((uint)(((b & 0xF) << 12) | ((bytes[num] & 0x3F) << 6)) | (bytes[num + 1] & 0x3Fu))) : '\ufffd');
					num += 2;
					utfbytes[num3++] = (byte)(c & 0xFFu);
					utfbytes[num3++] = (byte)((int)c >> 8);
					if ((b == Conv.REP_CHAR_UTF8[0] && bytes[num - 2] == Conv.REP_CHAR_UTF8[1] && bytes[num - 1] == Conv.REP_CHAR_UTF8[2]) || ccb || c != '\ufffd')
					{
						break;
					}
					throw new DecoderFallbackException(I18nStringResourceManager.GetErrorMesg("FAIL_CONV_TO_UNICODE"));
				}
				case 15:
				{
					if (num + 2 >= num2)
					{
						if (!ccb)
						{
							throw new DecoderFallbackException(I18nStringResourceManager.GetErrorMesg("FAIL_CONV_TO_UNICODE"));
						}
						flag = false;
						num--;
						break;
					}
					char[] array = new char[2];
					int num5 = 0;
					if ((b != 240 || (bytes[num] & 0xC0) != 128 || (bytes[num] & 0x30) == 0 || (bytes[num + 1] & 0xC0) != 128 || (bytes[num + 2] & 0xC0) != 128) && (b < 241 || b > 243 || (bytes[num] & 0xC0) != 128 || (bytes[num + 1] & 0xC0) != 128 || (bytes[num + 2] & 0xC0) != 128) && (b != 244 || (bytes[num] & 0xF0) != 128 || (bytes[num + 1] & 0xC0) != 128 || (bytes[num + 2] & 0xC0) != 128))
					{
						array[0] = '\ufffd';
						num5 = 1;
					}
					else
					{
						array[0] = (char)((uint)(((((((b & 7) << 2) | ((bytes[num] >> 4) & 3)) - 1) & 0xF) << 6) | ((bytes[num] & 0xF) << 2)) | ((uint)(bytes[num + 1] >> 4) & 3u) | 0xD800u);
						array[1] = (char)((uint)((bytes[num + 1] & 0xF) << 6) | (bytes[num + 2] & 0x3Fu) | 0xDC00u);
						num5 = 2;
					}
					num += 3;
					if (num5 == 1)
					{
						utfbytes[num3++] = 253;
						utfbytes[num3++] = byte.MaxValue;
						if (!ccb)
						{
							throw new DecoderFallbackException(I18nStringResourceManager.GetErrorMesg("FAIL_CONV_TO_UNICODE"));
						}
					}
					else if (num3 + 3 >= num4)
					{
						flag = false;
						num -= 4;
					}
					else
					{
						utfbytes[num3++] = (byte)(array[0] & 0xFFu);
						utfbytes[num3++] = (byte)((int)array[0] >> 8);
						utfbytes[num3++] = (byte)(array[1] & 0xFFu);
						utfbytes[num3++] = (byte)((int)array[1] >> 8);
					}
					break;
				}
				default:
					utfbytes[num3++] = 253;
					utfbytes[num3++] = byte.MaxValue;
					if (!ccb)
					{
						throw new DecoderFallbackException(I18nStringResourceManager.GetErrorMesg("FAIL_CONV_TO_UNICODE"));
					}
					break;
				}
			}
			utfCount = num3 - utfOffset;
			return num - offset;
		}

		public override int ConvertBytesToUTF16(byte[] bytes, int offset, int count, byte[] utfbytes, int utfOffset, ref int utfCount, bool ccb)
		{
			return ConvertBytesToUTF16Impl(bytes, offset, count, utfbytes, utfOffset, ref utfCount, ccb);
		}

		public override int ConvertBytesToChars(IList<ArraySegment<byte>> bytes, int bytesOffset, int bytesCount, char[] chars, int charOffset, ref int charCount, bool bUseReplacementChar)
		{
			if (bytes.Count == 1)
			{
				return ConvertBytesToChars(bytes[0].Array, bytes[0].Offset + bytesOffset, bytesCount, chars, charOffset, ref charCount, bUseReplacementChar);
			}
			return UTF16ConvUtility.ConvertArraySegListToCharsImpl(bytes, bytesOffset, bytesCount, chars, charOffset, ref charCount, bUseReplacementChar, ConvertBytesToCharsInstance);
		}

		public override int GetCharsLength(byte[] bytes, int byteOffset, int byteCount)
		{
			int bytesCounted = 0;
			return GetCharsLengthImpl(bytes, byteOffset, byteCount, ref bytesCounted);
		}

		public override int GetCharsLength(ArraySegment<byte> bytes, int bytesOffset, int bytesCount)
		{
			int bytesCounted = 0;
			return GetCharsLengthImpl(bytes.Array, bytes.Offset + bytesOffset, bytesCount, ref bytesCounted);
		}

		public override int GetCharsLength(IList<ArraySegment<byte>> bytes, int bytesOffset, int bytesCount)
		{
			return UTF16ConvUtility.GetCharsLengthListSegs(bytes, bytesOffset, bytesCount, GetCharsLengthInstance);
		}

		public override int GetBytesOffset(IList<ArraySegment<byte>> bytes, int charCount)
		{
			return UTF16ConvUtility.GetBytesOffsetListSegs(bytes, charCount, GetBytesOffsetInstance);
		}
	}
}
